#pragma once

#include <atomic>
#include <iostream>
#include <vector>
#include <fstream>
#include <string>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <random>
#include <sstream>
#include <openssl/sha.h>
#include <openssl/rand.h>
#include <openssl/evp.h>
#include <iomanip>
#include <boost/algorithm/string.hpp>

// 临时路径名
const std::string temp_path = "./temp/";

namespace ns_util
{
    class TimeUtil // TimeUtil: 获取当前时间
    {
    public:
        static std::string GetTimeStamp()
        {
            struct timeval _time;
            gettimeofday(&_time, NULL);
            return std::to_string(_time.tv_sec) + "." + std::to_string(_time.tv_usec); // 秒级 与 毫秒级
        }

        static std::string GetDateTime()
        {
            time_t now = time(0);
            struct tm tstruct;
            char buf[80];
            tstruct = *localtime(&now);
            strftime(buf, sizeof(buf), "%Y-%m-%d %X", &tstruct);
            return buf; // 格式化时间
        }
    };

    class PathUtil // PathUtil: 构建不同类型的文件路径
    {
    public:
        // 添加后缀
        static std::string AddSuffix(const std::string &file_name, const std::string &suffix)
        {
            std::string path_name = temp_path;
            path_name += file_name;
            path_name += suffix;
            return path_name;
        }

        // ↓ 添加相关路径 ↓
        static std::string Src(const std::string &file_name)
        {
            return AddSuffix(file_name, ".cpp");
        }

        static std::string Bin(const std::string &file_name)
        {
            return AddSuffix(file_name, ".bin");
        }

        static std::string Exe(const std::string &file_name)
        {
            return AddSuffix(file_name, ".exe");
        }

        static std::string CompileError(const std::string &file_name)
        {
            return AddSuffix(file_name, ".compile_error");
        }

        static std::string StdOut(const std::string &file_name)
        {
            return AddSuffix(file_name, ".stdout");
        }

        static std::string StdIn(const std::string &file_name)
        {
            return AddSuffix(file_name, ".stdin");
        }

        static std::string StdErr(const std::string &file_name)
        {
            return AddSuffix(file_name, ".stderr");
        }

        static std::string CompilerError(const std::string &file_name)
        {
            return AddSuffix(file_name, ".compile_error");
        }
    };

    class FileUtil
    {
    public:
        static bool RemoveFile(const std::string& file_name) {
            // 尝试删除文件
            if (std::remove(file_name.c_str()) != 0) {
                std::cerr << "Error deleting file: " << file_name << std::endl;
                return false;  // 删除失败
            }
            return true;  // 删除成功
        }

        static bool SetContent(const std::string& _file_name, const std::string& content) {
            std::ofstream ofs(_file_name, std::ios::binary); // 二进制创建
            if(!ofs.is_open()) {
                std::cerr << "file open error";
                return false;
            }

            ofs.write(&content[0], content.size());

            if(!ofs.good()) {
                std::cerr << "write file error";
                return false;
            }

            ofs.close();

            if(chmod(_file_name.c_str(), 0777) != 0) {
                std::cerr << "chmod file error";
                return false;
            } // 修改文件权限

            return true;
        } // 将content的内容设置到文件中

        // 文件是否存在
        static bool IsFileExist(const std::string &path_name)
        {
            struct stat st;
            if (stat(path_name.c_str(), &st) == 0)
            {
                // 获取属性成功，文件存在
                return true;
            }
            return false;
        }

        // 标识唯一文件
        static std::string UniqueFileName()
        {
            static std::atomic_uint file_id(0);
            file_id++;
            // 时间戳 与 原子操作 确保唯一
            // 原子操作： 原子操作是指在多线程环境下，对某一个操作，在执行过程中不会被中断，并且是一个原子操作。
            std::string id = std::to_string(file_id);
            std::string timestamp = TimeUtil::GetTimeStamp();
            return timestamp + "_" + id;
        }

        // 向目标文件写入内容
        static bool WriteFile(const std::string &target, const std::string &content)
        {
            std::ofstream out(target);
            if (!out.is_open())
            {
                std::cout << "WriteFile: 文件打开失败" << std::endl;
                return false;
            }

            out.write(content.c_str(), content.size());
            out.close();
            return true;
        }

        // 从目标文件读取内容
        // target: 输入型参数，目标文件名
        // content: 输出型参数，保存读取的内容
        static bool ReadFile(const std::string &target, std::string *content, bool KeepLineBreaks) // KeepLineBreaks: 是否保留换行符
        {
            (*content).clear();

            std::ifstream in(target);
            if (!in.is_open())
            {
                std::cout << "ReadFile: 文件打开失败" << std::endl;
                return false;
            }

            std::string inputLine;
            while (getline(in, inputLine))
            {
                (*content) += inputLine;
                if (KeepLineBreaks)
                    (*content) += "\n";
            }
            in.close();
            return true;
        }

        static std::string read_api_key(const std::string& file_path) {
            std::ifstream file(file_path);  // 打开文件
            std::string api_key;

            if (file.is_open()) {
                std::getline(file, api_key);  // 读取文件的第一行（即密钥）
                file.close();  // 关闭文件
            } else {
                std::cerr << "无法打开文件: " << file_path << std::endl;
            }

            return api_key;
        }
    };

    class StringUtil
    {
    public:
        static std::string hashPassword(const std::string &password) {
            unsigned char hash[SHA256_DIGEST_LENGTH];
            SHA256_CTX sha256;
            SHA256_Init(&sha256);
            SHA256_Update(&sha256, password.c_str(), password.length());
            SHA256_Final(hash, &sha256);

            std::stringstream ss;
            for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) {
                ss << std::setw(2) << std::setfill('0') << std::hex << (int)hash[i];
            }
            return ss.str();
        }

        // str: 输入型参数，目标字符串
        // target: 输出型参数，保存切分的结果
        // sep：分隔符
        static void SplitString(const std::string &str, std::vector<std::string> *target, const std::string &sep)
        {
            // 使用boost库的split
            boost::split(*target, str, boost::is_any_of(sep), boost::token_compress_off);
        }

        // 生成一个随机的32位session_id
        static std::string generate_session_id()
        {
            std::stringstream ss;
            std::random_device rd;
            std::mt19937 mt(rd());
            std::uniform_int_distribution<int> dist(0, 15);
            for (int i = 0; i < 32; ++i)
            {
                int r = dist(mt);
                ss << (r < 10 ? char('0' + r) : char('a' + r - 10));
            }
            return ss.str();
        }

        // 从cookies中提取session_id
        static std::string extract_session_id(const std::string &cookies)
        {
            std::string session_id;
            std::istringstream cookie_stream(cookies);
            std::string cookie;

            while (std::getline(cookie_stream, cookie, ';'))
            {
                std::string::size_type pos = cookie.find("session_id=");
                if (pos != std::string::npos)
                {
                    session_id = cookie.substr(pos + 11); // 11 is the length of "session_id="
                    break;
                }
            }
            return session_id;
        }
    };
}